home *** CD-ROM | disk | FTP | other *** search
- //
- // BEGIN FLOCK GPL
- //
- // Copyright Flock Inc. 2005-2007
- // http://flock.com
- //
- // This file may be used under the terms of of the
- // GNU General Public License Version 2 or later (the "GPL"),
- // http://www.gnu.org/licenses/gpl.html
- //
- // Software distributed under the License is distributed on an "AS IS" basis,
- // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- // for the specific language governing rights and limitations under the
- // License.
- //
- // END FLOCK GPL
- //
-
- const CLASS_ID = Components.ID("{C711A35C-8949-4D01-9676-47E71F1A78F4}");
- const CLASS_NAME = "Flock Results Search Module";
- const CONTRACT_ID = "@flock.com/flock-search-flock;1";
- const flockISearchService = Components.interfaces.flockISearchService;
-
- const FLOCK_NS = "http://flock.com/rdf#";
- const NC_NS = "http://home.netscape.com/NC-rdf#";
-
- const RDFCU = Components.classes["@mozilla.org/rdf/container-utils;1"].getService(Components.interfaces.nsIRDFContainerUtils);
- const RDFS = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService);
-
- function flockSearchAPIFlock()
- {
- this._favService = Components.classes["@mozilla.org/rdf/datasource;1?name=flock-favorites"].getService(Components.interfaces.nsIRDFDataSource);
- this._logger = Components.classes["@flock.com/logger;1"].createInstance(Components.interfaces.flockILogger);
- this._logger.init("search");
- var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService);
- var bundle = sbs.createBundle("chrome://flock/locale/search/search.properties");
- this.serviceName = bundle.GetStringFromName("flock.search.api.flock");
- };
-
- flockSearchAPIFlock.prototype = {
-
- _searchListener: null,
- _maxResults: null,
- _searchesOutstanding: null,
- _resultsBookmarks: null,
- _resultsHistory: null,
- _currentQuery: null,
- RDFS: null,
- shortName: "flock",
- icon: "rdf:http://flock.com/rdf#icon",
- ref: "urn:flock:search:results",
- mDS: null,
- fullResultsUrl: "flock://search/?query=",
-
- search: function(aQuery, aNumResults, aListener, aDatasource)
- {
- this._searchListener = aListener;
- this._maxResults = aNumResults;
-
- this._currentQuery = aQuery;
-
- // get references to the services we use
- var searchService = Components.classes["@flock.com/lucene/flockLucene;1"].getService(Components.interfaces.flockILucene);
- this.RDFS = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService);
- var prefService = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
-
- // save a ref to the ds passed in
- this.mDS = aDatasource;
-
- var normalizedQuery = this.normalizeQuery(aQuery);
-
- this._logger.debug("query: \"" + aQuery + "\" => \"" + normalizedQuery + "\"");
-
- var showHistory = prefService.getBoolPref("flock.search.flyout.showHistory") && prefService.getBoolPref("flock.service.indexer.indexWebHistory");
-
- // clear results
- this._resultsBookmarks = [];
- this._resultsHistory = [];
-
- // start the searchs
- if (showHistory) {
- this._searchesOutstanding = 2;
- searchService.search(normalizedQuery, "bookmark", this._maxResults, this);
- searchService.search(normalizedQuery, "history", this._maxResults, this);
- } else {
- this._searchesOutstanding = 1;
- searchService.search(normalizedQuery, "bookmark", this._maxResults, this);
- }
- },
-
- normalizeQuery: function(input)
- {
- var output;
- var in_quotes = false;
-
- // strip leading spaces
- while (input.length && input[0]==" ") {
- // chop off the first character
- input = input.substr(1);
- }
-
- // Convert to lowercase for the wildcard search
- input = input.toLowerCase();
-
- // add leading plus
- output = "+";
- while (input.length) {
- if (input[0] == "\"") {
- if (in_quotes) {
- in_quotes = false;
- } else {
- in_quotes = true;
- // FIXME: remove spaces from the start of quoted strings
- }
- }
-
- // escape special chars
- if ("&|!(){}[]^~*?:\\".indexOf(input[0]) >= 0) {
- output = output + "\\";
- }
-
- output = output + input[0];
-
- if (!in_quotes && input[0] == " " && input.length > 1) {
- // put a plus before every word
- output = output + "+";
- }
-
- input = input.substr(1);
- }
-
- // remove trailing spaces
- var removed_spaces = false;
- while (output.length > 0 && output[output.length - 1] == " ") {
- output = output.substr(0, output.length - 1);
- removed_spaces = true;
- }
-
- // if we're in a quoted string we should close that
- if (in_quotes) {
- output = output + "\"";
- }
-
- // if theres an incomplete word
- if ((!removed_spaces) && (output[output.length - 1] != "\"")) {
- // search for partial matches
- output = output + "*";
- }
-
- return output;
- },
-
- // flockILuceneListener
- onSearchComplete: function(aNumResults, aResults) {
- this._logger.debug("onSearchComplete: hits: " + aNumResults);
-
- if (aNumResults > 0) {
- while (aResults.hasMoreElements()) {
- var result = aResults.getNext();
- result.QueryInterface(Components.interfaces.flockILuceneResult);
- this._logger.debug("foundResults: " + result.type + " " + result.URI);
-
- switch (result.type) {
- case "bookmark":
- this._resultsBookmarks.push([result.URL, result.title]);
- break;
- case "history":
- this._resultsHistory.push([result.URL, result.title]);
- break;
- }
- }
- }
-
- this._searchesOutstanding--;
-
- if (this._searchesOutstanding == 0) {
- this._returnResults();
- }
- },
-
- _returnResults: function()
- {
- this._logger.debug("_returnResults");
-
- var resultSet = this.mDS;
- var resultSetRoot = this.RDFS.GetResource("urn:flock:search:results");
- var rootContainer = RDFCU.MakeSeq(resultSet, resultSetRoot);
-
- var c;
- var urlHash = {};
- var url;
- var title;
- var favicon;
- var result;
- var resultCount = 0;
-
- // return bookmark results
- for (c = 0; c < this._resultsBookmarks.length && resultCount < this._maxResults; c++) {
- url = this._resultsBookmarks[c][0];
- title = this._resultsBookmarks[c][1];
- favicon = "chrome://browser/skin/flock/search/documentIcon16.png";
- infoicon = "chrome://flock/skin/common/star16.png";
-
- // skip duplicate bookmarks (online bookmarks)
- if (urlHash[url] == true) {
- continue;
- }
-
- urlHash[url] = true;
-
- result = this.RDFS.GetAnonymousResource();
-
- rootContainer.AppendElement(result);
-
- resultSet.Assert(result, this.RDFS.GetResource("http://home.netscape.com/NC-rdf#URL"), this.RDFS.GetLiteral(url), true);
- resultSet.Assert(result, this.RDFS.GetResource("http://home.netscape.com/NC-rdf#Name"), this.RDFS.GetLiteral(title), true);
- resultSet.Assert(result, this.RDFS.GetResource("http://home.netscape.com/NC-rdf#favicon"), this.RDFS.GetLiteral(favicon), true);
- resultSet.Assert(result, this.RDFS.GetResource(FLOCK_NS + "infoicon"), this.RDFS.GetLiteral(infoicon), true);
-
- resultCount++;
- }
-
- // fill in history results
- for (c = 0; c < this._resultsHistory.length && resultCount < this._maxResults; c++) {
- url = this._resultsHistory[c][0];
- title = this._resultsHistory[c][1];
- favicon = "chrome://browser/skin/flock/search/documentIcon16.png";
-
- // skip history results that have already been returned as bookmarks
- if (urlHash[url] == true) {
- continue;
- }
-
- result = this.RDFS.GetAnonymousResource();
-
- rootContainer.AppendElement(result);
-
- resultSet.Assert(result, this.RDFS.GetResource("http://home.netscape.com/NC-rdf#URL"), this.RDFS.GetLiteral(url), true);
- resultSet.Assert(result, this.RDFS.GetResource("http://home.netscape.com/NC-rdf#Name"), this.RDFS.GetLiteral(title), true);
- resultSet.Assert(result, this.RDFS.GetResource("http://home.netscape.com/NC-rdf#favicon"), this.RDFS.GetLiteral(favicon), true);
-
- resultCount++;
- }
-
- this._searchListener.foundResults(resultCount, resultSet, this.shortName, this._currentQuery);
- // JMC - Trying to fix leak of this listener
- this._searchListener = null;
- },
-
- // nsIClassInfo
- getInterfaces: function(aCount)
- {
- var interfaces = [Components.interfaces.flockISearchService, Components.interfaces.nsIClassInfo, Components.interfaces.flockILuceneListener];
- aCount.value = interfaces.length;
- return interfaces;
- },
-
- // nsIClassInfo
- getHelperForLanguage: function(aLanguage)
- {
- return null;
- },
-
- // nsIClassInfo
- contractID: CONTRACT_ID,
-
- // nsIClassInfo
- classDescription: CLASS_NAME,
-
- // nsIClassInfo
- classID: CLASS_ID,
-
- // nsIClassInfo
- implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
-
- // nsIClassInfo
- flags: Components.interfaces.nsIClassInfo.SINGLETON,
-
- // nsISupports
- QueryInterface: function(aIID)
- {
- if (!aIID.equals(Components.interfaces.nsISupports) && !aIID.equals(Components.interfaces.flockISearchService) && !aIID.equals(Components.interfaces.nsIClassInfo) && !aIID.equals(Components.interfaces.flockILuceneListener))
- throw Components.results.NS_ERROR_NO_INTERFACE;
- return this;
- }
-
- };
-
- /******************************************************************************
- * XPCOM Functions for construction and registration
- ******************************************************************************/
- var Module = {
- _firstTime: true,
- registerSelf: function(aCompMgr, aFileSpec, aLocation, aType)
- {
- if (this._firstTime) {
- this._firstTime = false;
- throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
- }
- aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
- aCompMgr.registerFactoryLocation(CLASS_ID, CLASS_NAME, CONTRACT_ID, aFileSpec, aLocation, aType);
-
- // register search provider
- var catmgr = Components.classes["@mozilla.org/categorymanager;1"]
- .getService(Components.interfaces.nsICategoryManager);
- catmgr.addCategoryEntry("flockISearchService", "flock", CONTRACT_ID, true, true);
- },
-
- unregisterSelf: function(aCompMgr, aLocation, aType)
- {
- aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
- aCompMgr.unregisterFactoryLocation(CLASS_ID, aLocation);
- },
-
- getClassObject: function(aCompMgr, aCID, aIID)
- {
- if (!aIID.equals(Components.interfaces.nsIFactory))
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
- if (aCID.equals(CLASS_ID))
- return Factory;
- throw Components.results.NS_ERROR_NO_INTERFACE;
- },
-
- canUnload: function(aCompMgr) { return true; }
- };
-
- var Factory = {
- createInstance: function(aOuter, aIID)
- {
- if (aOuter != null)
- throw Components.results.NS_ERROR_NO_AGGREGATION;
- return (new flockSearchAPIFlock()).QueryInterface(aIID);
- }
- };
-
- function NSGetModule(aCompMgr, aFileSpec) { return Module; }
-
-